package com.sl.au.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.DVConstraint;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFName;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.sl.au.entity.PartBaseInfo;
import com.sl.au.entity.PartCondition;
import com.sl.au.entity.User;
import com.sl.au.entity.GridAreaInfo;
import com.sl.au.entity.Hierarchy;
import com.sl.au.entity.Option;
import com.sl.au.entity.Part;
import com.sl.au.service.PartService;
import com.sl.au.service.DeleteService;
import com.sl.au.service.GridAreaInfoService;
import com.sl.au.service.HierarchyService;
import com.sl.au.service.OptionService;
import com.sl.au.service.PartBaseInfoService;
import com.sl.au.service.PartConditionService;
import com.sl.utils.ExdeUtil;
import com.sl.utils.MsgHelper;

/**
 * 部件基本属性管理
 * 
 * @author yangdi
 *
 */
@RestController
@RequestMapping(value = "/ui/partBaseInfo")
public class PartBaseInfoController extends BaseController {

	@Autowired
	private HierarchyService hierarchyService;
	@Autowired
	PartService partService;
	@Autowired
	PartBaseInfoService partBaseInfoService;
	@Autowired
	GridAreaInfoService gridAredInfoService;
	@Autowired
	OptionService optionService;
	@Autowired
	PartConditionService partConditionService;
	@Autowired
	DeleteService deleteService;

	private boolean isRightFile(MultipartFile file) {
		String fileName = file.getOriginalFilename();
		return fileName != null && !"".equals(fileName) && (fileName.endsWith(".xlsx") || fileName.endsWith(".xls"));
	}

	/**
	 * 文件上传
	 * 
	 * @param file
	 * @return
	 */
	@RequestMapping(value = "/uploadMb", method = RequestMethod.POST)
	public MsgHelper uploadMb(MultipartFile file) {

		int nowRow = 0;// 当前行
		if (isRightFile(file)) {
			// 将文件上传到指定的磁盘中
			String excelPath = this.getUploadFilePath(this.fileUploadPath, "excel/partBaseInfo", file);
			// 从磁盘中读取文件信息并上传到数据库中
			excelPath = this.fileUploadPath + excelPath;
			try {
				Workbook workbook = null;
				String fileName = file.getOriginalFilename();
				if (fileName.endsWith(".xls")) {// 处理低版本
					workbook = new HSSFWorkbook(new FileInputStream(new File(excelPath)));
				}
				if (fileName.endsWith(".xlsx")) {// 处理高版本
					workbook = new XSSFWorkbook(new FileInputStream(new File(excelPath)));
				}
				Sheet sheet = workbook.getSheetAt(0);
				int lastRowNum = sheet.getLastRowNum();

				for (int i = 1; i <= lastRowNum; i++) {// 遍历每一行
					nowRow++;
					Row row = sheet.getRow(i);
					if (row == null) {
						continue;
					}
					// 部件名称
					if (row.getCell(0) == null) {
						continue;
					}
					String partName = findByType(row.getCell(0));
					// 部件标识码
					if (row.getCell(1) == null) {
						continue;
					}
					String partIdentify = "" + ((Double) Double.parseDouble(findByType(row.getCell(1)))).intValue();
					// 所属部件
					if (row.getCell(2) == null) {
						continue;
					}
					Part part = partService.findByName(findByType(row.getCell(2)));
					// 所属网格
					if (row.getCell(3) == null) {
						continue;
					}
					GridAreaInfo gridAreaInfo = gridAredInfoService.findByName(findByType(row.getCell(3)));
					// 权属部门
					if (row.getCell(4) == null) {
						continue;
					}
					Hierarchy hierarchy = hierarchyService.getRepository().findByGroupName(findByType(row.getCell(4)))
							.get(0);
					// 生产厂家
					if (row.getCell(5) == null) {
						continue;
					}
					String manufacturer = findByType(row.getCell(5));
					// 生产时间
					if (row.getCell(6) == null) {
						continue;
					}
					Date productionTime = new SimpleDateFormat("yyyy/MM/dd").parse(findByType(row.getCell(6)));
					// 安装时间
					if (row.getCell(7) == null) {
						continue;
					}
					Date installationTime = new SimpleDateFormat("yyyy/MM/dd").parse(findByType(row.getCell(7)));
					// 图标地址
					if (row.getCell(8) == null) {
						continue;
					}
					String iconAddress = "icon/PartBaseInfo/" + UUID.randomUUID().toString()
							+ findByType(row.getCell(8));
					// 经度
					if (row.getCell(9) == null) {
						continue;
					}
					double longitude = Double.parseDouble(findByType(row.getCell(9)));
					// 纬度
					if (row.getCell(10) == null) {
						continue;
					}
					double latitude = Double.parseDouble(findByType(row.getCell(10)));
					// 状态
					if (row.getCell(11) == null) {
						continue;
					}
					Option state = optionService.getRepository()
							.findByGroupAndTitle("部件状态", findByType(row.getCell(11))).get(0);
					if (row.getCell(12) == null) {
						continue;
					}

					int partOrderNum = ((Double) Double.parseDouble(findByType(row.getCell(12)))).intValue();

					// 接口地址
					if (row.getCell(13) == null) {
						continue;
					}
					String interfaceAddress = findByType(row.getCell(13));
					// 接口端口
					if (row.getCell(14) == null) {
						continue;
					}
					String interfacePort = findByType(row.getCell(14));
					// 设备编码
					if (row.getCell(15) == null) {
						continue;
					}
					String deviceIdentify = "" + ((Double) Double.parseDouble(findByType(row.getCell(15)))).intValue();
					// 管理部门
					if (row.getCell(16) == null) {
						continue;
					}
					Hierarchy manageHierarchy = hierarchyService.getRepository()
							.findByGroupName(findByType(row.getCell(16))).get(0);
					// 维护部门
					if (row.getCell(17) == null) {
						continue;
					}
					Hierarchy maintainHierarchy = hierarchyService.getRepository()
							.findByGroupName(findByType(row.getCell(17))).get(0);

					// 保存
					PartBaseInfo p = new PartBaseInfo();
					p.setDeviceIdentify(deviceIdentify);
					p.setDivisionIdentify(gridAreaInfo.getDivision().getDivisionIdentify());
					p.setGridAreaInfo(gridAreaInfo);
					p.setHierarchy(hierarchy);
					p.setHierarchyIdentify(hierarchy.getGroupIdentify());
					p.setIconAddress(iconAddress);
					p.setInstallationTime(installationTime);
					p.setInterfaceAddress(interfaceAddress);
					p.setInterfacePort(interfacePort);
					p.setLatitude(latitude);
					p.setLongitude(longitude);
					p.setMaintainHierarchy(maintainHierarchy);
					p.setManufacturer(manufacturer);
					p.setManageHierarchy(manageHierarchy);
					p.setOrderNum(hierarchy.getGroupOrder());
					p.setPart(part);
					p.setPartIdentify(partIdentify);
					p.setPartName(partName);
					p.setPartOrderNum(partOrderNum);
					p.setProductionTime(productionTime);
					p.setState(state); 
					partBaseInfoService.getRepository().save(p);
				}
			} catch (Exception e) {
				e.printStackTrace();
				return MsgHelper.failed().put("msg", "第 " + nowRow + " 行数据错误 ");

			}
		}
		return MsgHelper.success().put("msg", "上传成功!");
	}

	/**
	 * <pre>
	 * 	CellType 类型 值
	   	CELL_TYPE_NUMERIC 数值型 0
		CELL_TYPE_STRING 字符串型 1
		CELL_TYPE_FORMULA 公式型 2
		CELL_TYPE_BLANK 空值 3
		CELL_TYPE_BOOLEAN 布尔型 4
		CELL_TYPE_ERROR 错误 5
	 * </pre>
	 * 
	 * @param cellType
	 * @return
	 */

	private String findByType(Cell cell) {

		switch (cell.getCellType()) {
		case Cell.CELL_TYPE_NUMERIC:
			if (HSSFDateUtil.isCellDateFormatted(cell)) {
				Date d = cell.getDateCellValue();
				return new SimpleDateFormat("yyyy/MM/dd").format(d);
			}
			return cell.getNumericCellValue() + "";
		case Cell.CELL_TYPE_STRING:
			return cell.getStringCellValue();

		default:
			return "";
		}

	}

	/**
	 * 部件基本信息模板下载
	 */
	@RequestMapping(value = "/downloadMb", method = RequestMethod.POST)
	public void downloadMb(HttpServletResponse response) {
		String fileName = "download.xls";
		HSSFWorkbook wb = null;
		OutputStream outputStream = null;

		try {
			// 1 创建workbook
			wb = new HSSFWorkbook();
			// 2 创建sheet
			HSSFSheet sheet = wb.createSheet("部件基本信息模板");
			// 3 创建表头行
			HSSFRow row = sheet.createRow(0);
			// 4 创建单元格
			row.createCell(0).setCellValue("部件名称");
			row.createCell(1).setCellValue("部件标识码");
			row.createCell(2).setCellValue("所属部件");
			row.createCell(3).setCellValue("所属网格");
			row.createCell(4).setCellValue("权属部门");
			row.createCell(5).setCellValue("生产厂家");
			row.createCell(6).setCellValue("生产时间");
			row.createCell(7).setCellValue("安装时间");
			row.createCell(8).setCellValue("图标地址");
			row.createCell(9).setCellValue("经度");
			row.createCell(10).setCellValue("纬度");
			row.createCell(11).setCellValue("状态");
			row.createCell(12).setCellValue("部件层级排序号");
			row.createCell(13).setCellValue("接口地址");
			row.createCell(14).setCellValue("接口端口");
			row.createCell(15).setCellValue("设备编码");
			row.createCell(16).setCellValue("管理部门");
			row.createCell(17).setCellValue("维护部门");

			// 初始化100行模板数据
			List<Part> parts = partService.getRepository().findAll();// 所属部件
			String[] partNames = null;
			int len = 0;
			if (parts != null && parts.size() > 0) {
				partNames = new String[parts.size()];
				for (Part p : parts) {
					partNames[len++] = p.getPartName();
				}
			}
			if (partNames != null && partNames.length > 0) {
				 buildSelectInfo(0, 99, 2,2, partNames, sheet,wb);
			}

			// 初始化网格信息
			List<GridAreaInfo> grids = gridAredInfoService.getRepository().findAll();
			String[] gridNames = null;
			len = 0;
			if (grids != null && grids.size() > 0) {
				gridNames = new String[grids.size()];
				for (GridAreaInfo g : grids) {
					gridNames[len++] = g.getGridName();
				}
			}
			if (gridNames != null && gridNames.length > 0) {
				 buildSelectInfo(0, 99, 3, 3, gridNames, sheet,wb);
			}

			// 初始化部门信息
			List<Hierarchy> hierarchies = hierarchyService.getRepository().findAll();
			String[] hierarchyNames = null;
			len = 0;
			if (hierarchies != null && hierarchies.size() > 0) {
				hierarchyNames = new String[hierarchies.size()];
				for (Hierarchy h : hierarchies) {
					hierarchyNames[len++] = h.getGroupName();
				}
			}

			if (hierarchyNames != null && hierarchyNames.length > 0) {
				buildSelectInfo(1, 99, 4, 4, hierarchyNames, sheet,wb);
				// 创建管理部门
				buildSelectInfo(1, 99, 16, 16, hierarchyNames, sheet,wb);
				// 创建维护部门
				buildSelectInfo(1, 99, 17, 17, hierarchyNames, sheet,wb);
			}

			// 创建状态信息
			List<Option> states = optionService.getRepository().findByGroup("部件状态");
			String[] titles = null;
			len = 0;
			if (states != null && states.size() > 0) {
				titles = new String[states.size()];
				for (Option o : states) {
					titles[len++] = o.getTitle();
				}
			}
			if (titles != null && titles.length > 0) {
				buildSelectInfo(1, 99, 11, 11, titles, sheet,wb);
			}

			// 将文件写入流
			outputStream = response.getOutputStream();
			response.setCharacterEncoding("utf-8");
			response.setContentType("multipart/form-data");
			response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
			wb.write(outputStream);
			outputStream.flush();
			outputStream.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (outputStream != null) {
					outputStream.close();
					outputStream = null;
				}

				if (wb != null) {
					wb.close();
					wb = null;
				}

			} catch (IOException e) {

				e.printStackTrace();
			}
		}

	}

	private void buildSelectInfo(int beginRow, int endRow, int beginCol, int endCol, String[] names, HSSFSheet sheet, HSSFWorkbook wb) {
		// 创建隐藏域
		String hiddenSheet="hiddenSheet"+beginCol;
		HSSFSheet hidden = wb.createSheet(hiddenSheet); 
		 for (int i = 0, length = names.length; i < length; i++) { 
             hidden.createRow(endRow + i).createCell(beginCol).setCellValue(names[i]);
         } 
		 Name name = wb.createName();
		 name.setNameName(hiddenSheet);
		 name.setRefersToFormula(hiddenSheet+"!A1:A"+(names.length+endRow));
		// 设置下拉列表
		CellRangeAddressList regionsPart = new CellRangeAddressList(0, 99, beginCol, endCol);
		// 创建下拉列表数据
		DVConstraint constraintPart = DVConstraint.createFormulaListConstraint(hiddenSheet);
		// 绑定
		HSSFDataValidation dataValidationPart = new HSSFDataValidation(regionsPart, constraintPart);
		wb.setSheetHidden(1, true); // 1隐藏、0显示
		sheet.addValidationData(dataValidationPart);

	}

	@RequestMapping(method = RequestMethod.GET)
	public ModelAndView index() {
		ModelAndView modelAndView = this.createLayoutView("partBaseInfo/partBaseInfoindex");
		List<Option> options = optionService.getRepository().findByGroup("部件状态");
		List<Option> conditions = optionService.getRepository().findByGroup("条件分类");
		modelAndView.addObject("options", options);
		modelAndView.addObject("conditions", conditions);
		return modelAndView;
	}

	/**
	 * 初始数据
	 * 
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "getpage", method = RequestMethod.POST)
	public Map<String, Object> getPage(HttpServletRequest request) {
		Map<String, Object> map = new HashMap<String, Object>();
		int start = Integer.parseInt(request.getParameter("start"));
		int length = Integer.parseInt(request.getParameter("length"));
		String key = request.getParameter("key");
		List<PartBaseInfo> modules = null;
		int count = 0;

		modules = partBaseInfoService.getPage(start, length, key, "createTime", Sort.Direction.DESC);
		count = partBaseInfoService.getCount(key);

		map.put("data", modules);
		map.put("draw", request.getParameter("draw"));
		map.put("recordsFiltered", count);
		map.put("recordsTotal", count);
		return map;
	}

	/**
	 * 
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "getpartsbyparttype", method = RequestMethod.GET)
	public Map<String, Object> getpartsbyparttype(HttpServletRequest request) {
		Map<String, Object> map = new HashMap<String, Object>();

		String parttypeid = request.getParameter("parttypeid");
		List<PartBaseInfo> modules = null;
		if (StringUtils.hasText(parttypeid)) {
			modules = this.partBaseInfoService.getRepository().getAllByPartType(parttypeid);
			map.put("data", modules);
		}
		map.put("code", 1);
		return map;
	}

	/**
	 * 删除信息
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping("/deleteCondition/{id}")
	public MsgHelper deleteCondition(@PathVariable("id") String id) {
		MsgHelper msgHelper = MsgHelper.success();
		partConditionService.getRepository().delete(id);
		msgHelper.setMsg("删除部件条件信息成功！");
		return msgHelper;
	}

	/**
	 * 删除信息
	 * 
	 * @param id
	 * @return
	 */
	@RequestMapping("/delete/{id}")
	public MsgHelper deletePartBaseInfo(@PathVariable("id") String id) {
		MsgHelper msgHelper = MsgHelper.success();
		Map<String, Object> map = new HashMap<String, Object>();
		map = deleteService.deleteInfo(this.datasourceName, User.class, id);
		if (map.get("code").equals(0)) {
			partBaseInfoService.getRepository().delete(id);
			msgHelper.setMsg("部件信息删除成功！");
		} else {
			msgHelper.setMsg((String) map.get("msg"));
		}

		return msgHelper;
	}

	/**
	 * 保存部件信息及上传图标
	 * 
	 * @param partBaseInfo
	 * @param file
	 * @return
	 */
	@RequestMapping(value = "savePartBaseInfoWithFile", method = RequestMethod.POST)
	public Map<String, Object> saveDetailWithFile(PartBaseInfo partBaseInfo,
			@RequestParam(value = "file", required = false) MultipartFile file) {
		Map<String, Object> map = new HashMap<String, Object>();
		int code = -1;
		Map<String, String[]> info = request.getParameterMap();
		String sInstallationTime = info.get("installation")[0] + " 00:00:00";
		String sProductionTime = info.get("production")[0] + " 00:00:00";
		String pattern = "yyyy-MM-dd HH:mm:ss";
		Date installationTime = ExdeUtil.str2Date(sInstallationTime, pattern);
		Date productionTime = ExdeUtil.str2Date(sProductionTime, pattern);
		partBaseInfo.setInstallationTime(installationTime);
		partBaseInfo.setProductionTime(productionTime);
		if (file.getOriginalFilename() != null && !"".equals(file.getOriginalFilename())) {
			// 注意路径的构建
			String url = getUploadIconFilePath(this.fileUploadPath, "icon/PartBaseInfo", file);
			partBaseInfo.setIconAddress(url);
		}
		GridAreaInfo gridAreaInfo = gridAredInfoService.GetGridAreaInfoByCoordinate(partBaseInfo.getLongitude(),
				partBaseInfo.getLatitude());
		partBaseInfo.setGridAreaInfo(gridAreaInfo);
		partBaseInfo = partBaseInfoService.savePartBaseInfo(partBaseInfo);
		if (partBaseInfo == null) {
			code = 0;
			map.put("code", code);
			map.put("msg", "该层级已绑定满，新增失败！");
		} else {
			code = 1;
			map.put("code", code);
			map.put("msg", "部件信息保存成功！");
			map.put("attributes", partBaseInfo);
		}

		return map;
	}

	/**
	 * 条件页面数据
	 * 
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "getConditionPage", method = RequestMethod.POST)
	public Map<String, Object> getConditionPage(HttpServletRequest request) {
		Map<String, Object> map = new HashMap<String, Object>();
		int start = Integer.parseInt(request.getParameter("start"));
		int length = Integer.parseInt(request.getParameter("length"));
		String key = request.getParameter("key");
		String partId = request.getParameter("partId");
		List<PartCondition> modules = null;
		int count = 0;

		modules = partConditionService.getPage(start, length, partId, key, "createTime", Sort.Direction.DESC);
		count = partConditionService.getCount(partId, key);

		map.put("data", modules);
		map.put("draw", request.getParameter("draw"));
		map.put("recordsFiltered", count);
		map.put("recordsTotal", count);
		return map;
	}

	@RequestMapping(value = "saveCondition", method = RequestMethod.POST)
	public MsgHelper saveCondition(@RequestBody Map<String, Object> map) {
		MsgHelper msgHelper = MsgHelper.success();
		;
		PartCondition savePartCondition = null;

		String id = (String) map.get("id");
		String partId = (String) map.get("part");
		String conditionTypeId = (String) map.get("conditionType");
		String content = (String) map.get("content");

		Option conditionType = optionService.getRepository().findOne(conditionTypeId);
		PartBaseInfo part = partBaseInfoService.getRepository().findOne(partId);

		if (id.equals("")) {
			savePartCondition = new PartCondition();
			msgHelper.setMsg("部件条件信息新增成功！");
		} else {
			savePartCondition = partConditionService.getRepository().findOne(id);
			msgHelper.setMsg("部件条件信息保存成功！");
		}
		savePartCondition.setConditionType(conditionType);
		savePartCondition.setPartBaseInfo(part);
		savePartCondition.setContent(content);

		partConditionService.getRepository().save(savePartCondition);

		return msgHelper;
	}

	@RequestMapping(value = "/removeConditionAll", method = RequestMethod.POST)
	public Map<String, Object> removeConditionAll(@RequestBody Map<String, Object> map) {
		Map<String, Object> msg = new HashMap<String, Object>();
		ArrayList<String> dataInfo = (ArrayList<String>) map.get("dataInfo");
		String[] infos = new String[dataInfo.size()];
		dataInfo.toArray(infos);
		partConditionService.getRepository().deleteAllPartConditionByIds(infos);
		msg.put("msg", "信息移除成功!");
		return msg;
	};
}
